Skip to main content

ORSANCO Flows - Frontend Design Document

1. Overview

This document outlines the frontend design for the ORSANCO River Flows system upgrade. The primary goals are to improve data query capabilities, enhance map navigation, and provide a dedicated bulk download interface for long-term flow data analysis.

1.1 Key Objectives

  • Enable multi-parameter queries (flow, velocity, stage) over extended time periods (2009-present)
  • Improve station search and map navigation functionality
  • Create a dedicated bulk download page separate from visualization
  • Implement token-based API authentication
  • Enhance user experience with Material-UI components
  • Maintain consistent design patterns across the application

1.2 Technology Stack

  • Framework: React
  • UI Library: Material-UI (MUI)
  • Map Library: Current implementation
  • State Management: React Context API
  • API Communication: REST with token authentication
  • Hosting: Azure Static Web App

2. Application Structure

2.1 Page Architecture

The application consists of four main pages:

/
├── Overview (existing - informational)
├── Map (enhanced)
├── Daily Flows (enhanced)
└── Bulk Download (new)

2.2 Navigation Flow

3. Page Designs

3.1 Overview Page

Status: No changes required

Keep existing informational content about the system.


3.2 Map Page (Enhanced)

3.2.1 Layout

┌────────────────────────────────────────────────────────────┐
│ [Logo] ORSANCO Flows [🌓 Theme] [🔍] [📍] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ │
│ │
│ MAP VIEWPORT │
│ (Current Implementation) │
│ │
│ │
│ │
└────────────────────────────────────────────────────────────┘

3.2.2 Top Action Bar

The action bar sits in the top-right corner with the following items:

Site-Wide Actions:

  • Theme Toggle (🌓): Switch between light/dark mode
  • Settings (⚙️): Application settings modal

Page-Specific Actions:

  • Search for River Station (🔍): Opens station search modal
  • Search for Location (📍): Opens geocoder search modal

3.2.3 Search for River Station Modal

┌──────────────────────────────────────────────────┐
│ Search for River Station [X] │
├──────────────────────────────────────────────────┤
│ │
│ River │
│ [Select River ▼] │
│ │
│ Reach │
│ [Select Reach ▼] │
│ │
│ Station │
│ [Search stations... ] 🔍 │
│ (Autocomplete with dropdown) │
│ │
│ [Cancel] [Go] │
└──────────────────────────────────────────────────┘

Behavior:

  • River dropdown populates from /api/rivers/
  • Selecting river filters reach dropdown
  • Station autocomplete searches within selected reach
  • "Go" button zooms map to selected station
  • Closes modal automatically after navigation

3.2.4 Search for Location Modal

┌──────────────────────────────────────────────────┐
│ Search for Location [X] │
├──────────────────────────────────────────────────┤
│ │
│ Enter city, address, or coordinates │
│ [Type location... ] 🔍 │
│ │
│ Suggestions: │
│ • Cincinnati, OH │
│ • Owensboro, KY │
│ • Louisville, KY │
│ │
│ [Cancel] [Go] │
└──────────────────────────────────────────────────┘

Behavior:

  • Uses geocoding service to convert text to coordinates
  • Zooms map to resolved location
  • Shows error message if location not found

3.2.5 Map Interaction

Station Click Behavior:

  1. User clicks station marker on map
  2. Station is marked as "active" (highlighted)
  3. Active station ID is stored in context
  4. Popup shows basic station info with "View Data" button
  5. "View Data" navigates to Daily Flows page with station pre-selected

Camera State:

  • Map remembers camera position (zoom level and center) when navigating away
  • Returns to same position when user returns to Map page
  • Resets to default only on app refresh or explicit reset

3.3 Daily Flows Page (Enhanced)

3.3.1 Layout

┌────────────────────────────────────────────────────────────┐
│ [Logo] ORSANCO Flows [🌓 Theme] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ Daily Flows │
├────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Station Selection │ │
│ │ ┌────────────┬────────────┬──────────────────────┐ │ │
│ │ │River │Reach │Station │ │ │
│ │ │[Select ▼] │[Select ▼] │[Search... ] 🔍 │ │ │
│ │ └────────────┴────────────┴──────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Date Range │ │
│ │ Start Date: [📅 11/01/2024] Days: [30] │ │
│ │ [Load Data] │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ FLOW CHART (Min/Avg/Max) │ │
│ │ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Download: [CSV] [JSON] │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────┘

3.3.2 Station Selection Component

Tiered Dropdown System:

  1. River Dropdown: Select from all available rivers
  2. Reach Dropdown: Filtered by selected river
  3. Station Autocomplete: Search/filter stations within reach, with optional multi-select support

Data Flow:

Default Behavior:

  • If user arrives from Map page with active station, pre-populate all three fields
  • Station selection persists in context until changed
  • Changing river resets reach and station
  • Changing reach resets station only

3.3.3 Date Range Controls

  • Start Date: MUI DatePicker component
  • Number of Days: Numeric input (default: 30, max: 365 for this page)
  • Load Data: Button to fetch and render chart

Current Limitation:

  • This page maintains the current limitation of ~1 year max
  • For longer periods, users should use Bulk Download page

3.4 Bulk Download Page (New)

This is the primary addition to support extended multi-parameter queries without visualization overhead.

3.4.1 Layout Overview

┌────────────────────────────────────────────────────────────┐
│ [Logo] ORSANCO Flows [🌓 Theme] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ Bulk Data Download │
├──────────────────────────────────────────────────────────┬─┤
│ ┌─────────────────────┬─────────────────────────────┐ │ │
│ │ SINGLE STATION │ MULTIPLE STATIONS (FID) │ │ │
│ │ SELECTION (Left) │ SELECTION (Right) │ │Q│
│ │ │ │ │U│
│ │ │ │ │E│
│ │ │ │ │R│
│ │ │ │ │Y│
│ │ │ │ │ │
│ │ │ │ │H│
│ │ │ │ │I│
│ │ │ │ │S│
│ │ │ │ │T│
│ │ │ │ │O│
│ │ │ │ │R│
│ │ │ │ │Y│
│ └─────────────────────┴─────────────────────────────┘ │ │
│ ┌──────────────────────────────────────────────────┐ │ │
│ │ QUERY PARAMETERS (Bottom) │ │ │
│ └──────────────────────────────────────────────────┘ │ │
└──────────────────────────────────────────────────────────┴─┘

3.4.2 Detailed Layout

┌────────────────────────────────────────────────────────────────────────────────┐
│ Bulk Data Download │
├──────────────────────────────────────────────┬─────────────────────────────────┤
│ SINGLE STATION SELECTION │ QUERY HISTORY │
│ ┌──────────────────────────────┐ │ ┌─────────────────────────────┐ │
│ │ River │ │ │ 🟢 Complete │ │
│ │ [Select River ▼] │ │ │ Station 699.5 │ │
│ │ │ │ │ 2009-2024, All params │ │
│ │ Reach │ │ │ [Download] [Delete] │ │
│ │ [Select Reach ▼] │ │ ├─────────────────────────────┤ │
│ │ │ │ │ 🔵 Processing... │ │
│ │ Station(s) │ │ │ Stations 700.0-705.5 │ │
│ │ [Search stations... ] 🔍 │ │ │ 2020-2024, Flow only │ │
│ │ (Autocomplete w/ multi) │ │ │ │ │
│ │ │ │ ├─────────────────────────────┤ │
│ │ Selected: Station 699.5 │ │ │ ⏱️ Queued │ │
│ │ Station 700.2 │ │ │ Station 606.0 │ │
│ └──────────────────────────────┘ │ │ 2009-2024, All params │ │
│ │ └─────────────────────────────┘ │
│ OR │ │
│ │ Storage Used: 234 MB / 10 GB │
│ MULTIPLE STATIONS (FID) │ [Clear All Completed] [Refresh] │
│ ┌──────────────────────────────┐ │ │
│ │ Enter comma-separated FIDs │ └─────────────────────────────────┘
│ │ │
│ │ [1, 5, 23, 45, 67, ...] │
│ │ │
│ │ │
│ │ │
│ └──────────────────────────────┘
├────────────────────────────────────────────────────────────────────────────────┤
│ QUERY PARAMETERS │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ Date Range │ │
│ │ Start: [📅 01/01/2009] End: [📅 11/11/2024] │ │
│ │ │ │
│ │ Parameters │ │
│ │ ☑ Flow ☑ Velocity ☑ Stage │ │
│ │ │ │
│ │ Aggregation │ │
│ │ ○ None (Raw 15-min data) │ │
│ │ ● Daily ( ☑ Min ☑ Max ☑ Average ) │ │
│ │ ○ Hourly ( ☐ Min ☐ Max ☐ Average ) │ │
│ │ │ │
│ │ [Submit Query] │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────┘

3.4.3 Component Breakdown

Left Panel: Single Station Selection

River Dropdown

  • Fetches rivers from /api/rivers/
  • MUI Select component
  • On change: Clear reach and station selections

Reach Dropdown

  • Filtered based on selected river
  • Fetches from /api/reaches/?river={riverId}
  • On change: Clear station selection

Station Autocomplete (Multi-Select)

  • MUI Autocomplete with multiple={true}
  • Searches within selected reach
  • As user types, filters matching stations by name or river mile
  • Selected stations appear as chips below the input
  • Each chip has an X to remove
Center Panel: Multiple Stations (FID List)

FID Text Input

  • Large text area for comma-separated FIDs
  • Example placeholder: "1, 5, 23, 45, 67, 89, ..."
  • Validates on blur: checks if FIDs exist
  • Shows error if any FID is invalid
  • Use case: User has pre-identified list of stations from external analysis

Mutual Exclusivity:

  • If user enters FIDs, disable left panel (single station selection)
  • If user selects stations on left, disable FID input
  • Clear button to reset and enable both sides
Right Panel: Query History

Query List Items

Each query shows:

  • Status indicator (colored circle)
    • 🟢 Green: Complete
    • 🔵 Blue: Processing
    • ⏱️ Gray: Queued
    • 🔴 Red: Failed
  • Station name(s) or count
  • Date range summary
  • Parameters requested
  • Action buttons: [Download][Delete]

Status Display:

  • Auto-refreshes every 10 seconds if any query is Queued/Processing
  • Manual refresh button available
  • "Clear All Completed" button removes all successful downloads

Storage Gauge:

  • Shows total storage used by cached queries
  • Example: "234 MB / 10 GB"
  • Visual progress bar
  • Queries auto-delete after 30 days OR manual delete
Bottom Panel: Query Parameters

Date Range

  • Start Date: MUI DatePicker (earliest available: 2009)
  • End Date: MUI DatePicker (latest: today)
  • No hard limit on range (can request full 2009-2024)

Parameters Checkboxes

  • Flow, Velocity, Stage
  • Must select at least one
  • All three selected by default

Aggregation Radio + Checkboxes

  • None: Raw 15-minute increment data
  • Daily: Aggregated by day with sub-options
    • Min, Max, Average (multiple can be selected)
  • Hourly: Aggregated by hour with sub-options
    • Min, Max, Average (multiple can be selected)

Submit Query Button

  • Validates inputs
  • Sends POST request to /api/bulk-download/
  • Adds new query to Query History with "Queued" status
  • Disables button while submitting

3.4.4 User Flows

Flow 1: Single Station Query

Flow 2: Multiple Station Query (FID List)

3.4.5 CSV Output Format

File Naming Convention:

For single station:

20090101_20241111_StationName699-5.csv

For multiple stations (in ZIP):

20090101_20241111_Stations_Multiple.zip
├── 20090101_20241111_Station699-5.csv
├── 20090101_20241111_Station700-2.csv
└── 20090101_20241111_Station705-0.csv

CSV Structure (Wide Format):

Example with Daily aggregation and all parameters:

DateTime,Flow_Min,Flow_Max,Flow_Avg,Velocity_Min,Velocity_Max,Velocity_Avg,Stage_Min,Stage_Max,Stage_Avg
2024-01-01,12500,15300,13800,2.3,3.1,2.7,450.2,451.8,450.9
2024-01-02,13200,16100,14500,2.5,3.3,2.9,451.0,452.5,451.6

Example with raw data and only Flow parameter:

DateTime,Flow
2024-01-01 00:00:00,12500
2024-01-01 00:15:00,12550
2024-01-01 00:30:00,12600

ZIP Compression:

  • Individual CSVs > 50MB are auto-zipped
  • Multiple station queries are always zipped
  • ZIP file size displayed in Query History

4. Component Library

4.1 Reusable Components

StationSelector

Props:

  • river: Selected river ID
  • reach: Selected reach ID
  • station: Selected station ID(s)
  • multiSelect: Boolean (default: false)
  • onChange: Callback function

Behavior:

  • Tiered dropdowns for River → Reach → Station
  • Autocomplete for station search
  • Optional multi-select support

QueryHistoryCard

Props:

  • query: Query object {id, status, stations, dateRange, parameters, downloadUrl}
  • onDownload: Callback
  • onDelete: Callback

Displays:

  • Status indicator
  • Query summary
  • Action buttons

AggregationSelector

Props:

  • aggregationType: "none" | "daily" | "hourly"
  • aggregators: ["min", "max", "avg"]
  • onChange: Callback

Displays:

  • Radio buttons for type
  • Checkboxes for aggregator functions

4.2 Context Providers

AuthContext

  • Manages authentication token
  • Handles token refresh
  • Provides auth status and user info

StationContext

  • Stores selected/active station from map
  • Persists across page navigation
  • Provides station selection methods

QueryContext

  • Manages bulk download query state
  • Tracks query history
  • Provides query submission methods

MapContext

  • Stores map camera state (zoom, center)
  • Remembers position across navigation

5. Theme & Styling

5.1 Material-UI Theme

Color Palette (Light Mode):

  • Primary: #1976d2 (Blue)
  • Secondary: #424242 (Gray)
  • Background: #fafafa
  • Surface: #ffffff

Color Palette (Dark Mode):

  • Primary: #90caf9 (Light Blue)
  • Secondary: #bdbdbd (Light Gray)
  • Background: #121212
  • Surface: #1e1e1e

5.2 Status Colors

  • Queued: #9e9e9e (Gray)
  • Processing: #2196f3 (Blue)
  • Complete: #4caf50 (Green)
  • Failed: #f44336 (Red)

5.3 Typography

  • Headers: Roboto, Bold
  • Body: Roboto, Regular
  • Monospace (FID input): 'Roboto Mono', monospace

6. Responsive Design

6.1 Breakpoints

  • Desktop: ≥ 1200px (default layout)
  • Tablet: 768px - 1199px (adjust bulk download to stack vertically)
  • Mobile: < 768px (single column, simplified interface)

6.2 Bulk Download Page Responsive Behavior

Desktop (≥ 1200px):

  • Side-by-side layout: Single Selection | FID Input | Query History

Tablet (768px - 1199px):

  • Stack vertically: Single Selection, FID Input, Query Parameters, Query History

Mobile (< 768px):

  • Full-width stacked components
  • Query History as expandable section at bottom
  • Simplified station selector (single select only)

7. Accessibility

7.1 WCAG 2.1 AA Compliance

  • Color contrast ratios ≥ 4.5:1
  • Keyboard navigation support
  • ARIA labels on all interactive elements
  • Focus indicators on all focusable elements

7.2 Screen Reader Support

  • Semantic HTML structure
  • Alt text for icons
  • Status announcements for query state changes

8. Performance Considerations

8.1 Optimization Strategies

  • Lazy load Bulk Download page components
  • Debounce autocomplete searches (300ms)
  • Paginate query history (show last 50, load more on scroll)
  • Memoize station selector component
  • Virtual scrolling for long station lists

8.2 Loading States

  • Skeleton screens for initial data load
  • Spinner for query submission
  • Progress indicators for query processing

9. Error Handling

9.1 User-Facing Error Messages

API Errors:

  • Connection failed: "Unable to connect to server. Please check your connection and try again."
  • Timeout: "Request timed out. The query may be too large. Try reducing the date range."
  • Authentication failed: "Session expired. Please refresh the page and log in again."

Validation Errors:

  • No station selected: "Please select at least one station."
  • No parameters selected: "Please select at least one parameter (Flow, Velocity, or Stage)."
  • Invalid date range: "End date must be after start date."
  • Invalid FID: "FID '999' not found. Please check your input."

9.2 Error UI Components

  • Toast Notifications: For transient errors (auto-dismiss after 5s)
  • Inline Errors: For form validation (red text below input)
  • Error Boundaries: Catch component errors and show fallback UI

10. Future Enhancements

10.1 Potential Features (Not in Current Scope)

  • Email/SMS notifications when query completes
  • Saved query templates
  • Query scheduling (e.g., weekly exports)
  • Data visualization preview in bulk download
  • Compare multiple stations side-by-side
  • Export to additional formats (Excel, Parquet)
  • API endpoint documentation page
  • User accounts with query history

10.2 QA Features (Future)

  • Optional QA filtering during download:
    • Remove negative values
    • Flag anomalies (e.g., >3 std dev from moving average)
    • Interpolate missing data
  • QA report summary in downloaded ZIP

11. Implementation Notes

11.1 Development Phases

Phase 1: Foundation (2 weeks)

  • Set up MUI theme and components
  • Implement authentication flow
  • Create reusable StationSelector component

Phase 2: Map Enhancements (1 week)

  • Add action bar to map page
  • Implement search modals
  • Add camera state persistence

Phase 3: Daily Flows Enhancement (1 week)

  • Add StationSelector to Daily Flows page
  • Implement station persistence from map
  • Update data fetching logic

Phase 4: Bulk Download Page (3 weeks)

  • Create page layout and components
  • Implement query submission
  • Build Query History UI
  • Add Azure Table/Blob Storage integration

Phase 5: Testing & Polish (1 week)

  • End-to-end testing
  • Performance optimization
  • Accessibility audit
  • Bug fixes

11.2 Testing Strategy

  • Unit tests for all components (Jest + React Testing Library)
  • Integration tests for user flows
  • E2E tests for critical paths (Playwright)
  • Accessibility testing (axe-core)
  • Performance testing (Lighthouse)

12. Appendix

12.1 Wireframe References

See inline ASCII diagrams in sections 3.2-3.4

12.2 User Stories

As a biologist, I want to search for a station by river mile so that I can quickly find flow data for a field site.

As a data analyst, I want to download 20 years of flow data for multiple stations so that I can calculate long-term flow statistics.

As a field technician, I want to match flow data with sampling events so that I can correlate water quality with river conditions.

As a manager, I want to see query history so that I can track what data has been downloaded for reporting purposes.

12.3 Glossary

  • FID: Feature ID, unique identifier for each station
  • River Mile: Distance in miles from the mouth of a river
  • Reach: A specific section of a river between two points
  • Stage: Water surface elevation (though technically "elevation" in the system)
  • Aggregation: Statistical summarization of data over time periods

Document Version: 1.0 Last Updated: November 12, 2025 Author: Jake Status: Draft for Review